//= require "listview"

/* MusicNet Alignment Tool
 *
 * Copyright (c) 2010 Joe Lambert
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *  
 */

/** section: alignment
 * class ListContainer
 * 
 * Generic container for list of items 
 **/

var ListContainer = Class.create({	
	initialize: function(options)
	{	
		this.options = Object.extend({
			listViewClass: 'ListView',
			dataURL: 'ajax/ungrouped'
		}, options);
			
		this.surface = Builder.node('div', {id: this.id, className: 'list'});
		
		this.titleBar = Builder.node('div', {className: 'title'});
		this.surface.insert(this.titleBar);
		
		this.bodyDiv = Builder.node('div', {className: 'body'});
		this.surface.insert(this.bodyDiv);
		
		this.az = Builder.node('ul', {className: 'a2z'});
		this.bodyDiv.insert(this.az);
		
		this.listView = new window[this.options.listViewClass](this);
		this.bodyDiv.insert(this.listView.getSurface());
		
		this.currentPage = 'a';
		
		this.renderA2Z();
		
		this.loadData(this.currentPage);
		
		this.az.observe('click', function(event) {
			this.showPage(event.target.innerHTML);
		}.bind(this));
		
		this.surface.observe('click', function(event) {
			event.stop();
			this.focus();
		}.bind(this));
	},

/**
 * ListContainer#focus() -> null
 * 
 * Give focus to the list
 **/
	
	focus: function()
	{
		$$(".list.focus").each(function(elem){
			elem.removeClassName('focus');
		});
		
		this.surface.addClassName('focus');
	},

	
	// Never currently called as both Grouped and Ungrouped Lists overload
	loadData: function(page)
	{
		this.listView.setLoading();
		this.updateA2Z();
		
		new Ajax.Request(window.location.pathname+this.options.dataURL, {
			method: 'get',
			parameters: 'a2z='+page,
			onSuccess: function(transport) {
				this.data = transport.responseJSON.data;
				this.refresh();
			}.bind(this)
		});
	},

/**
 * ListContainer#refresh() -> null
 * 
 * Refresh the list
 **/
	
	refresh: function()
	{			
		this.listView.render();
		this.updateTitle();
	},

/**
 * ListContainer#renderA2Z() -> null
 * 
 * Render the A2Z list on the left of the column
 **/
	
	renderA2Z: function()
	{
		this.az.update();
		
		for(var i=65; i<=90; i++)
		{
			var c = String.fromCharCode(i).toLowerCase();
			var node = Builder.node('li', {id: this.tag+'-az-'+c, title: c.toUpperCase()+"'s"}, c);
			
			node.addClassName('enabled');
				
			if(c == this.currentPage)
				node.addClassName('selected');
			
			this.az.insert(node);
		}
	},

/**
 * ListContainer#updateA2Z() -> null
 * 
 * Update the currently selected A2Z items
 **/
	
	updateA2Z: function()
	{
		if($(this.tag+'-az-'+this.currentPage))			
		{
			this.az.getElementsBySelector('.selected').invoke('removeClassName', 'selected');	
			$(this.tag+'-az-'+this.currentPage).addClassName('selected');
		}
	},

/**
 * ListContainer#updateTitle() -> null
 * 
 * Update the list title
 **/
	
	updateTitle:function()
	{
		this.titleBar.update("List ("+this.data.length+" items)");
	},

/**
 * ListContainer#showPage(page) -> null
 * - page (String): The character of the page to display (a-z)
 *  
 * Show a specific A2Z page of the list
 **/
	
	showPage: function(page)
	{
		if(this.currentPage != page)
		{
			this.currentPage = page;
			this.loadData(this.currentPage);
		}
	},

/**
 * ListContainer#selectRowWithIndex(index) -> null
 * - index (Integer): The row index
 *  
 * Select the row with the given index
 **/
	
	selectRowWithIndex: function(index)
	{
		var li = this.list.childElements()[index];
		this.selectRow(li);
	},

/**
 * ListContainer#selectRow(li, addSelection) -> null
 * - li (HTMLDom): The <li> item to select
 * - addSelection (Boolean): Should the li be added to the current selection
 * 
 * Select a row
 **/
	
	selectRow: function(li, addSelection)
	{
		var id = li.id.split('-').last();
		var index = /row([0-9]+)/.exec(li.className);
		
		if(index)
			index = parseInt(index[1]);
		
		if(!addSelection)
		{
			for(i in this.selected)
			{
				if(this.selected[i])
					$(this.tag+'-listitem-'+i).removeClassName('selected');
			}
			
			this.selected = new Object();
			this.selected_count = 0;
		}
	
		this.selected[id] = true;
		this.selected_count++;
		this.current_index = index;
		
		li.addClassName('selected');
	},

/**
 * ListContainer#unselectRow(li) -> null
 * - li (HTMLDom): The <li> to deselect
 * 
 * Deselect a row
 **/
	
	unselectRow: function(li)
	{
		var index = li.id.split('-').last();
		this.selected[index] = false;
		this.selected_count--;
		li.removeClassName('selected');
	},

/**
 * ListContainer#singleClick(event) -> null
 * - event (Event): Click Event
 *  
 * Click Event handler
 **/
	
	singleClick: function(event)
	{
		var elem = this.getListItemFromEvent(event);
		var id = elem.id.split('-').last();
		
		if(this.selected[id])
			this.unselectRow(elem);
		else
			this.selectRow(elem, (event.metaKey || event.ctrlKey));
	},

/**
 * ListContainer#keyPress(event) -> null
 * - event (Event): KeyPress Event
 *  
 * KeyPress Event handler
 **/
	
	keyPress: function(event)
	{
		if(event.shiftKey && event.ctrlKey)
		{
			event.stop();
			
			if(event.keyCode >= 65 && event.keyCode <= 90) // a-z
			{
				var c = String.fromCharCode(event.keyCode).toLowerCase();
				this.showPage(c);
			}
		}
		
		if(event.keyCode == 39)	// RIGHT
		{
			event.stop();
			this.loadMetadata();
		}
		else if(event.keyCode == Event.KEY_DELETE)
		{
			this.trashSelectedVerify();
		}
		else
			this.listView.keyPress(event);
	},

/**
 * ListContainer#trashSelectedVerify() -> null
 *  
 * Prompt the user for if they wish to delete the selected items
 **/
	
	trashSelectedVerify: function()
	{
		var result = confirm("Are you sure you want to delete the selected items?");
		
		if(result)
			this.trashSelected();
	},

/**
 * ListContainer#trashSelected() -> null
 *  
 * Deletes the selected items
 **/
	
	trashSelected: function()
	{
		
	},

/**
 * ListContainer#loadMetadata() -> null
 *  
 * Loads the metadata about the selected items
 **/
	
	loadMetadata: function()
	{
		var selected = this.listView.getSelectedIndexes();
		
		var ids = new Array();
		
		for(var index in selected)
		{
			if(selected[index])
				ids.push(this.data[index].id);
		}
		
		document.fire('information:view', ids);
	},

/**
 * ListContainer#getSurface() -> null
 *  
 * Gets the drawing surface for this object
 **/
	
	getSurface: function()
	{
		return this.surface;
	},

/**
 * ListContainer#getListItemFromEvent() -> null
 *  
 * Helper function to get the <li> item that initiated an event
 **/
	
	getListItemFromEvent: function(event)
	{
		var elem = event.target;
		
		if(elem.tagName != 'LI')
			elem = elem.up('li');
			
		return elem;
	}
})